home *** CD-ROM | disk | FTP | other *** search
/ MacWorld: Complete Mac Interactive / Macworld Complete Mac Interactive CD)(1994).iso / The Best of BMUG / Fonts / Font Utilities / BitFont 1.0.1 / BitFont source / bitfont.c next >
C/C++ Source or Header  |  1991-12-01  |  55KB  |  2,299 lines

  1. /* BitFont version 1.0.1 12/1/91
  2.  
  3.    Author: Peter DiCamillo
  4.            Brown University Computing and Information Services
  5.            (401) 863-7582
  6.            Internet: Peter_DiCamillo@brown.edu
  7.            AppleLink: A0216
  8.            Compuserve: 73577,2036
  9.            America Online: PeterD11
  10.  
  11.    BitFont and it's source are in the public domain, and may be freely
  12.    distributed.
  13.            
  14.    Update History:
  15.    6/90        Initial version 1.0 for MacHack '90
  16.    12/1/91    Version 1.0.1: added support for format 6 subtable used in
  17.                    TrueType 'cmap' table.  The current TrueType version of
  18.                 the Chicago font uses a format 6 subtable.
  19.  
  20.    */
  21.  
  22. #include <QuickDraw.h>
  23. #include <Menus.h>
  24. #include <Dialogs.h>
  25. #include <Memory.h>
  26. #include <SegLoad.h>
  27. #include <Events.h>
  28. #include <OSEvents.h>
  29. #include <TextEdit.h>
  30. #include <ToolUtils.h>
  31. #include <Desk.h>
  32. #include <Windows.h>
  33. #include <Fonts.h>
  34. #include <Files.h>
  35. #include <Devices.h>
  36. #include <Serial.h>
  37. #include <Resources.h>
  38. #include <Packages.h>
  39. #include <Errors.h>
  40.  
  41. #include <StdIO.h>
  42. #include <StdLib.h>
  43. #include <String.h>
  44. #include <Strings.h>
  45.  
  46.  
  47. #define    NMENUS        6        /* number of defined menus */
  48. #define appleMenu    256
  49. #define    fileMenu    257
  50. #define editMenu    258
  51. #define fontMenu    259
  52. #define sizeMenu    260
  53. #define styleMenu    261
  54. #define fileMSize    6        /* size of File menu */
  55.  
  56. typedef struct {
  57.     short image_left;
  58.     short image_right;
  59.     short image_top;
  60.     short image_bottom;
  61.     short pen_right;
  62.     char  blank;
  63.     char  missing;
  64.     } imageinfo;
  65.  
  66. #define ATMProcsStatusCode 0
  67. #define ATMProcs3Version 3
  68.  
  69. typedef struct {
  70.     long    version;
  71.     short    (*fontAvailable)();
  72.     short    (*showText)();
  73.     short    (*xyshowText)();
  74.     } ATMProcs3;
  75.     
  76. typedef struct {
  77.     Fixed a, b, c, d, tx, ty;
  78.     } FixedMatrix;
  79.  
  80. typedef struct {
  81.     Fixed            version;
  82.     Fixed            fontRevision;
  83.     unsigned long    checkSumAdjustment;
  84.     unsigned long    magicNumber;
  85.     unsigned short    flags;
  86.     unsigned short    unitsPerEm;
  87.     long            l1;        /* start of created? */
  88.     long            created;
  89.     long            l2;        /* start of modified? */
  90.     long            modified;
  91.     short            xMin;
  92.     short            yMin;
  93.     short            xMax;
  94.     short            yMax;
  95.     unsigned short    macStyle;
  96.     unsigned short    lowestRecPPEM;
  97.     short            fontDirectionHint;
  98.     short            indexToLocFormat;
  99.     short            glyphDataFormat;
  100.     } fontheader;
  101.     
  102. typedef struct {
  103.     Fixed            version;
  104.     unsigned short    numTables;
  105.     unsigned short    searchRange;
  106.     unsigned short    entrySelector;
  107.     unsigned short    rangeShift;
  108.     } fontOffsetTable;
  109.     
  110. typedef struct {
  111.     unsigned long    tag;
  112.     unsigned long    checksum;
  113.     unsigned long    offset;
  114.     unsigned long    length;
  115.     } TableDirectory;
  116.     
  117. typedef struct {
  118.     unsigned short    version;
  119.     unsigned short    numTables;
  120.     } CharToGlyphHdr;
  121.     
  122. typedef struct {
  123.     unsigned short    platformId;
  124.     unsigned short    encodingId;
  125.     unsigned long    offset;
  126.     } CharToGlyphDir;
  127.     
  128. typedef struct {
  129.     unsigned short    format;        /* 0 */
  130.     unsigned short    length;
  131.     unsigned short    revision;
  132.     unsigned char    glyphIndexArray[256];
  133.     } CharToGlyphFmt0;
  134.  
  135. typedef struct {
  136.     unsigned short    format;        /* 6 */
  137.     unsigned short    length;
  138.     unsigned short    revision;
  139.     unsigned short    firstCode;
  140.     unsigned short    entryCount;
  141.     unsigned short    glyphIndexArray[256];    /* could be any length */
  142.     } CharToGlyphFmt6;
  143.     
  144. /* function prototypes */
  145.  
  146. void macinit(void);
  147. void definemenus(void);
  148. void macend(void);
  149. void hndmac(void);
  150. void updevent(GrafPtr msgptr);
  151. void drawgrid(char all);
  152. void menu_upd(void);
  153. void docommand(long mResult);
  154. void appl_menu(void);
  155. OSErr fontinit(void);
  156. void fontend(void);
  157. OSErr define_input(unsigned char *s, FMInput *r);
  158. OSErr openrfile(void);
  159. pascal Boolean onlyrsrc(FileParam *pb);
  160. void getfref(void);
  161. void closefile(void);
  162. int sizescan(void);
  163. void showextent(void);
  164. void chars2text(void);
  165. void analyse_char(unsigned char *addr, short charcode);
  166. int getbit(unsigned char *p, short n);
  167. int cvtleft(int i);
  168. int cvtright(int i);
  169. output_char(unsigned char *addr, short charcode);
  170. void showerr(unsigned char *s);
  171. void showmsg(unsigned char *s);
  172. void ctralrt(short a);
  173. void aboutdlg(void);
  174. void fsizedlg(void);
  175. void setfnum(DialogPtr dlgptr, short fs);
  176. void showfrec(void);
  177. pascal void frectext(WindowPtr dlgwindow, short item);
  178. void showtext(WindowPtr dlgwindow, short item);
  179. void showresrecord(unsigned char *s, WindowPtr dlgwindow);
  180. void showfheader(unsigned char *s, WindowPtr dlgwindow);
  181. unsigned long gettaboffset(Handle fh, unsigned long tag);
  182. unsigned long getfmtoffset(CharToGlyphHdr *cmpp, short format);
  183. void myDrawChar(short ch);
  184. void dlgline(unsigned char *s);
  185. void blankline(void);
  186. int newrscfile(void);
  187. int addfond(void);
  188. int addfont(void);
  189. void ctrwindow(GrafPtr wp);
  190. void framedflt(DialogPtr dlgptr);
  191.  
  192. #define CHARSPERPAGE 2        /* characters/page for data file with cc */
  193. #define NFNTID 1024            /* resource id to use for NFNT we create */
  194. #define DELAYTICKS 6        /* controls speed of display when imaging NFNT data */
  195.  
  196. char done;                    /* true to exit program */
  197.                             /* screen control rectangles */
  198.                             /* variables for my window */
  199. MenuHandle myMenus[NMENUS];
  200. struct EventRecord myEvent;
  201. char da_menu;
  202. short bigscreen;            /* screen at least 640 by 480 */
  203. Rect screenRect;            /* rectangle defining screen */
  204. Rect dragRect;                /* rectangle defining bounds for dragging */
  205. Rect sizeRect;                /* rectangle for resizing windows */
  206. struct Point sfgpoint;        /* standard file dialog locations */
  207. struct Point sfppoint;
  208.                             /* standard sizes for Size menu */
  209. short sizelist[] = {7, 9, 10, 12, 14, 18, 24, 36, 48, 60, 72};
  210. short fontsize = 9;            /* initialized to default size */
  211. FMInput dlginput;            /* Font input record for show record dialog */
  212. FMOutput dlgoutput;            /* Font output record for show record dialog */
  213. unsigned char dlgfname[256];    /* font name for show record dialog */
  214. short dlgxpos, dlgypos;        /* used to draw lines in dialog */
  215. short myref;                /* my resource manager reference number */
  216. short resref;                /* reference number of resource file to use */
  217. short myfref;                /* reference number for output file */
  218. char fileflag;                /* true if writing to a file */
  219. unsigned char imagebuff[8196];    /* buffer for character bit image */
  220. imageinfo scandata[257];    /* results from scanning font */
  221. WindowRecord wRecord;        /* window record for myWindow */
  222. WindowPtr myWindow;            /* handle to imaging display window */
  223. GrafPort WritePort;            /* Grafport for imaging */
  224. GrafPtr WritePtr;            /* pointer to GrafPort */
  225. BitMap WriteMap;            /* bitmap for GrafPort */
  226. char newpage;                /* counter for starting new pages */
  227. char cc;                    /* generate carriage control */
  228. char stdfont;                /* font with standard character codes */
  229. char atmfont;                /* set if this font can be imaged by ATM */
  230. char ttfont;                /* set for a TrueType™ font ('sfnt') */
  231. char atminit, atmavail;        /* flags for opening ATM driver */
  232. ATMProcs3 procs;            /* ATM proc pointers */
  233.                             /* variables for writing font resource file */
  234. short currvol;                    /* current volume reference */
  235. short rfile;                    /* file reference number */
  236. unsigned char rscfname[64];        /* file name */
  237. short rscvrefnum;                /* volume reference for file */
  238. Handle fondhandle;                /* handles for resources */
  239. Handle fonthandle;
  240. char fontwindow;            /* true = myWindow is FONT imaging */
  241.  
  242. main()
  243. {
  244.  
  245. macinit();                    /* initialize Mac */
  246. cc = 0;                        /* set to one to generate carriage control */
  247. stdfont = 1;                /* set to zero if ASCII mappings do not apply */
  248. myWindow = 0;                /* no window yet */
  249. atminit = 0;                /* ATM not initialized */
  250. done = 0;
  251. while (!done) hndmac();        /* handle Mac events and I/O */
  252. macend();
  253. }
  254.  
  255. void macinit(void)
  256. {
  257. short i; 
  258.  
  259.             /* set-up general Macintosh environment */
  260. MaxApplZone();                /* set-up for efficient storage use */
  261. for (i=0; i < 4; i++) MoreMasters();
  262. InitGraf(&qd.thePort);
  263. FlushEvents(everyEvent, 0);
  264. InitWindows();
  265. InitFonts();
  266. InitMenus();
  267. InitDialogs(0L);
  268. InitCursor();
  269. TEInit();
  270.  
  271.             /* set-up menus */
  272. myref = resref = CurResFile();
  273. da_menu = 0;
  274. definemenus();
  275.  
  276.             /* center alerts */
  277. ctralrt(256);
  278. ctralrt(260);
  279.  
  280. screenRect = qd.screenBits.bounds;
  281.  
  282. bigscreen = (((screenRect.bottom-screenRect.top) >= 480) &&
  283.              ((screenRect.right-screenRect.left) >= 640)); 
  284.  
  285.             /* calculate standard file dialog location*/
  286. sfppoint.h = (screenRect.right-screenRect.left-304)/2;
  287. sfgpoint.h = (screenRect.right-screenRect.left-348)/2;
  288. if (bigscreen) {
  289.     sfppoint.v = (screenRect.bottom-screenRect.top-184)/3;
  290.     sfgpoint.v = (screenRect.bottom-screenRect.top-200)/3;
  291.     }
  292. else {
  293.     sfppoint.v = (screenRect.bottom-screenRect.top-184)/2;
  294.     sfgpoint.v = (screenRect.bottom-screenRect.top-200)/2;
  295.     }
  296.  
  297. SetRect(&dragRect, 0, 24, screenRect.right-4, screenRect.bottom-4);
  298.  
  299. SetRect(&sizeRect, 50, 25, screenRect.right+1, screenRect.bottom+1);
  300.  
  301. fontwindow = 0;
  302. }
  303.  
  304. void definemenus(void)
  305. {
  306. short i, msize;
  307. Str255 itemname;
  308.  
  309. for (i=0; i < NMENUS; i++) {
  310.     myMenus[i] = GetMenu(256+i);
  311.     InsertMenu(myMenus[i], 0);
  312.     }
  313. AddResMenu(myMenus[0], 'DRVR');
  314. UseResFile(resref);
  315. AddResMenu(myMenus[3], 'FONT');
  316. UseResFile(myref);
  317. for (i=0; i < sizeof(sizelist)/sizeof(short); i++) {
  318.     sprintf(itemname, "%d pt", sizelist[i]);
  319.     c2pstr(itemname);
  320.     AppendMenu(myMenus[4], itemname);
  321.     if (sizelist[i] == fontsize) CheckItem(myMenus[4], i+1, true);
  322.     }
  323. AppendMenu(myMenus[4], "\P(-");
  324. AppendMenu(myMenus[4], "\POther...");
  325. /* initially select Geneva or first font */
  326. msize = CountMItems(myMenus[3]);
  327. if (msize > 0) {
  328.     CheckItem(myMenus[3], 1, true);
  329.     for (i=1; i <= msize; i++) {
  330.         GetItem(myMenus[3], i, itemname);
  331.         p2cstr(itemname);
  332.         if (strcmp(itemname, "Geneva") == 0) {
  333.             CheckItem(myMenus[3], 1, false);
  334.             CheckItem(myMenus[3], i, true);
  335.             break;
  336.             }
  337.         }
  338.     }
  339. /* default is plain text */
  340. CheckItem(myMenus[5], 1, true);
  341. appl_menu();
  342. }
  343.  
  344. void macend(void)
  345. {
  346. if (myWindow != 0) {
  347.     CloseWindow(myWindow);
  348.     myWindow = 0;
  349.     }
  350. }
  351.  
  352. void hndmac(void)
  353. {
  354. OSErr rc;
  355. short code;
  356. GrafPtr gp;
  357. unsigned short h, w;
  358. long l;
  359. WindowPtr whichWindow;
  360. struct WindowRecord * fw;
  361. char frontda;
  362.  
  363. rc = GetNextEvent(everyEvent, &myEvent);
  364. if (rc == 0)                        /* FALSE from GNE */
  365.     switch(myEvent.what) {
  366.         case nullEvent:
  367.                 fw = (WindowRecord *)FrontWindow();
  368.                 frontda = fw->windowKind < 0;
  369.                 if (frontda) {
  370.                     if (!da_menu) {
  371.                         da_menu = 1;
  372.                         SetItem(myMenus[1], fileMSize, "\pClose");
  373.                         appl_menu();
  374.                         }
  375.                     }
  376.                 else {
  377.                     if (da_menu) {
  378.                         da_menu = 0;
  379.                         SetItem(myMenus[1], fileMSize, "\pQuit");
  380.                         appl_menu();
  381.                         }
  382.                     }
  383.                 SystemTask();    /* run DAs, etc. */
  384.                 break;
  385.         default:
  386.                 return;
  387.         }
  388. else switch(myEvent.what) {            /* TRUE from GNE */
  389.         case mouseDown:
  390.             code = FindWindow(myEvent.where, &whichWindow);
  391.             switch (code) {
  392.             case inMenuBar:
  393.                 menu_upd();
  394.                 docommand(MenuSelect(myEvent.where));
  395.                 break;
  396.             case inSysWindow:
  397.                 SystemClick((EventRecord *)&myEvent, whichWindow);
  398.                 break;
  399.             case inDrag:
  400.                 if (whichWindow == FrontWindow())
  401.                     DragWindow(whichWindow, myEvent.where, (Rect *)&dragRect);
  402.                 else SelectWindow(whichWindow);
  403.                 break;
  404.             case inGoAway:
  405.                 break;
  406.             case inGrow:
  407.                 if (whichWindow == FrontWindow()) {
  408.                     GetPort(&gp);
  409.                     SetPort((GrafPtr)whichWindow);
  410.                     l = GrowWindow(whichWindow, myEvent.where, (Rect *)&sizeRect);
  411.                     h = l >> 16;
  412.                     w = l & 0x0000ffffL;
  413.                     SizeWindow(whichWindow, w, h, 0x100);
  414.                     SetPort(gp);
  415.                     }
  416.                 break;
  417.             case inContent:
  418.                 if (whichWindow != FrontWindow()) {
  419.                     SelectWindow(whichWindow);
  420.                     break;
  421.                     }
  422.                 break;
  423.  
  424.             case inZoomIn:
  425.             case inZoomOut:
  426.                 if (TrackBox(whichWindow, myEvent.where, code)) {
  427.                     if (((WindowPeek)whichWindow)->dataHandle == 0) break;
  428.                     GetPort(&gp);
  429.                     SetPort((GrafPtr)whichWindow);
  430.                     EraseRect(&(((WindowRecord *)whichWindow)->port.portRect));
  431.                     ZoomWindow(whichWindow, code, 0);
  432.                     SetPort(gp);
  433.                     }
  434.                 break;
  435.  
  436.             default:
  437.                 break;
  438.             }
  439.             break;
  440.  
  441.         case mouseUp:
  442.             break;
  443.  
  444.         case keyDown:
  445.         case autoKey:
  446.             if (myEvent.modifiers & cmdKey) {
  447.                 menu_upd();
  448.                 docommand(MenuKey(myEvent.message & 0xff));
  449.                 }
  450.             break;
  451.  
  452.         case activateEvt:
  453.             break;
  454.  
  455.         case updateEvt:
  456.             updevent((GrafPtr)myEvent.message);
  457.             break;
  458.  
  459.         case app4Evt:
  460.             break;
  461.  
  462.         default:    break;
  463.         }
  464. }
  465.  
  466. void updevent(GrafPtr msgptr)
  467. {
  468. GrafPtr gp;
  469.  
  470. GetPort(&gp);
  471. SetPort(msgptr);
  472. BeginUpdate(msgptr);
  473. if ((msgptr = myWindow) && (myWindow != 0)) {
  474.     if (!fontwindow) drawgrid(1);
  475.     }
  476. EndUpdate(msgptr);
  477. SetPort(gp);
  478. }
  479.  
  480. void drawgrid(char all)
  481. {
  482. short x1, x2, x3, x4;
  483. x1 = 71;
  484. x2 = 8;
  485. x3 = 263;
  486. x4 = 200;
  487. if (!all) {
  488.     x1 -= 8;
  489.     x2 -= 8;
  490.     x3 -= 8;
  491.     x4 -= 8;
  492.     }
  493. if (all) {
  494.     MoveTo(7, 7);
  495.     LineTo(264, 7);
  496.     LineTo(264, 264);
  497.     LineTo(7, 264);
  498.     LineTo(7, 7);
  499.     }
  500. MoveTo(x1, x2);
  501. LineTo(x1, x3);
  502. MoveTo(x2, x4);
  503. LineTo(x3, x4);
  504. }
  505.  
  506. void menu_upd(void)
  507. {
  508. short i;
  509.  
  510. if (da_menu) {
  511.     for (i = 1; i < fileMSize; i++)
  512.         DisableItem(myMenus[1], i);
  513.     CheckItem(myMenus[1], fileMSize, 0);
  514.     }
  515. else {
  516.     for (i = 1; i < fileMSize; i++)
  517.         EnableItem(myMenus[1], i);
  518.     CheckItem(myMenus[1], fileMSize, done << 8);
  519.     }
  520. }
  521.  
  522. void docommand(long mResult)
  523. {
  524. register short theItem, theMenu;
  525. unsigned char name[40];
  526. WindowRecord * fw;
  527. short i, msize, checked;
  528. static char nullstr[1] = {0};
  529. OSErr rc;
  530. unsigned char errtext[256];
  531.  
  532. theMenu = mResult >> 16;
  533. theItem = mResult & 0xff;
  534. switch(theMenu) {
  535.     case appleMenu:
  536.         if (theItem == 2) break;
  537.         if (theItem == 1) {
  538.             aboutdlg();
  539.             break;
  540.             }
  541.         GetItem(myMenus[0], theItem, name);
  542.         OpenDeskAcc(name);
  543.         break;
  544.     case fileMenu:
  545.         switch (theItem) {
  546.             case 1:
  547.                     rc = openrfile();
  548.                     if (rc != 0) break;
  549.                     HiliteMenu(0);
  550.                     appl_menu();
  551.                     ClearMenuBar();
  552.                     for (i=0; i < NMENUS; i++) {
  553.                         ReleaseResource((Handle)myMenus[i]);
  554.                         }
  555.                     definemenus();
  556.                     return;
  557.             case 2:
  558.             case 3:
  559.             case 4:
  560.             case 5:
  561.                     rc = fontinit();
  562.                     if (rc != 0) break;
  563.                     switch (theItem) {
  564.                         case 2:
  565.                                     fileflag = 0;
  566.                                     showfrec();
  567.                                     break;
  568.                         case 3:
  569.                                     rc = sizescan();
  570.                                     if (rc != 0) break;
  571.                                     showextent();
  572.                                     break;
  573.                         case 4:
  574.                                     getfref();
  575.                                     if (myfref == 0) break;
  576.                                     fileflag = 1;
  577.                                     newpage = CHARSPERPAGE;
  578.                                     showfrec();
  579.                                     rc = sizescan();
  580.                                     if (rc == 0) chars2text();
  581.                                     closefile();
  582.                                     break;
  583.                         case 5:                /* create bitmap font */
  584.                                     rc = sizescan();
  585.                                     if (rc != 0) break;
  586.                                     rc = newrscfile();
  587.                                     if (rc != 0) break;
  588.                                     fondhandle = fonthandle = 0;
  589.                                     rc = addfont();
  590.                                     if (rc == 0) rc = addfond();
  591.                                     CloseResFile(rfile);
  592.                                     if (rc == 0) {
  593.                                         rc = ResError();
  594.                                         if (rc != 0) {
  595.                                             sprintf(errtext,
  596.                                               "Error %d closing resource to file", rc);
  597.                                             showerr(errtext);
  598.                                             }
  599.                                         }
  600.                                     if (rc != 0) {
  601.                                         FSDelete(rscfname, rscvrefnum);
  602.                                         }
  603.                                     SetVol(0L, currvol);
  604.                                     if (fondhandle != 0) {
  605.                                         DisposHandle(fondhandle);
  606.                                         }
  607.                                     if (fonthandle != 0) {
  608.                                         DisposHandle(fonthandle);
  609.                                         }
  610.                                     break;
  611.                         default:
  612.                                     break;
  613.                         }
  614.                     fontend();
  615.                     break;
  616.             case 6:
  617.                     if (!da_menu) {
  618.                         done ^= 1;
  619.                         break;
  620.                         }
  621.                     else {
  622.                         fw = (WindowRecord *)FrontWindow();
  623.                         i = fw->windowKind;
  624.                         if (i<0) CloseDeskAcc(i);
  625.                         }
  626.             default: break;
  627.             }
  628.         break;
  629.     case editMenu:
  630.         SystemEdit(theItem-1);
  631.         break;
  632.     case fontMenu:
  633.         msize = CountMItems(myMenus[3]);
  634.         for (i=1; i <= msize; i++) {
  635.             CheckItem(myMenus[3], i, false);
  636.             }
  637.         CheckItem(myMenus[3], theItem, true);
  638.         break;
  639.     case sizeMenu:
  640.         msize = CountMItems(myMenus[4]);
  641.         if (theItem == msize) {
  642.             fsizedlg();
  643.             }
  644.         else {
  645.             fontsize = sizelist[theItem - 1];
  646.             }
  647.         checked = 0;
  648.         for (i=0; i < sizeof(sizelist)/sizeof(short); i++) {
  649.             CheckItem(myMenus[4], i+1, fontsize == sizelist[i]);
  650.             if (fontsize == sizelist[i]) checked = 1;
  651.             }
  652.         CheckItem(myMenus[4], msize, !checked);
  653.         break;
  654.     case styleMenu:
  655.         msize = CountMItems(myMenus[5]);
  656.         if (theItem == 1) {
  657.             CheckItem(myMenus[5], 1, true);
  658.             for (i=2; i <= msize; i++) {
  659.                 CheckItem(myMenus[5], i, false);
  660.                 }
  661.             }
  662.         else {
  663.             GetItemMark(myMenus[5], theItem, &i);
  664.             CheckItem(myMenus[5], theItem, i == noMark);
  665.             checked = noMark;
  666.             for (i=2; i <= msize; i++) {
  667.                 GetItemMark(myMenus[5], i, &checked);
  668.                 if (checked != noMark) break;
  669.                 }
  670.             CheckItem(myMenus[5], 1, checked == noMark);
  671.             }
  672.         break;
  673.     default:
  674.         break;
  675.     }
  676.     HiliteMenu(0);
  677.     appl_menu();
  678. }
  679.  
  680. void appl_menu(void)        /* enable correct application menus */
  681. {
  682. static char last_da = 2;    /* init to invalid value */
  683.  
  684. /* skip drawing menu if no changes from last time */
  685. if (last_da == da_menu) return;
  686. last_da = da_menu;        /* save values for next time */
  687.  
  688. if (da_menu) {
  689.     EnableItem(myMenus[2], 0);
  690.     DisableItem(myMenus[3], 0);
  691.     DisableItem(myMenus[4], 0);
  692.     DisableItem(myMenus[5], 0);
  693.     }
  694. else {
  695.     DisableItem(myMenus[2], 0);
  696.     EnableItem(myMenus[3], 0);
  697.     EnableItem(myMenus[4], 0);
  698.     EnableItem(myMenus[5], 0);
  699.     }
  700. DrawMenuBar();
  701. }
  702.  
  703. OSErr fontinit(void)
  704. {
  705. OSErr rc;
  706. FMOutput *p;
  707. long fontdef;
  708. CntrlParam c;
  709.  
  710. rc = define_input(dlgfname, &dlginput);
  711. if (rc != 0) {
  712.     showerr("Unable to define font input record");
  713.     return(rc);
  714.     }
  715. UseResFile(resref);
  716. p = FMSwapFont(&dlginput);
  717. UseResFile(myref);
  718. if (p == 0) {
  719.     showerr("Unable to define font output record");
  720.     return(1);
  721.     }
  722. dlgoutput = *p;
  723. rc = HandToHand(&(dlgoutput.fontHandle));
  724. if (rc != 0) { 
  725.     showerr("Not enough memory to copy font");
  726.     return(rc);
  727.     }
  728. HLock(dlgoutput.fontHandle);
  729. atmfont = ttfont = 0;
  730. if (((*(FontRec **)(dlgoutput.fontHandle))->fontType
  731.     & 0x8000) == 0) {
  732.     ttfont = 1;
  733.     }
  734. else {            /* check for ATM font */
  735.     if (!atminit) {
  736.         atminit = 1;
  737.         atmavail = 0;
  738.         rc = OpenDriver("\P.ATM", &c.ioCRefNum);
  739.         if (rc == 0) {
  740.             c.csCode = ATMProcsStatusCode;
  741.             *(ATMProcs3**)c.csParam = &procs;
  742.             procs.version = ATMProcs3Version;
  743.             atmavail = (PBStatus((ParmBlkPtr)(&c), 0)) == 0;
  744.             }
  745.         }
  746.     if (atmavail) {
  747.         fontdef = dlginput.family << 16;
  748.         fontdef += dlginput.face;
  749.         rc = (*procs.fontAvailable)(fontdef);
  750.         atmfont = (rc == 1);
  751.         }
  752.     }
  753. return(0);
  754. }
  755.  
  756. void fontend(void)
  757. {
  758. DisposHandle(dlgoutput.fontHandle);                
  759. }
  760.  
  761. OSErr define_input(unsigned char *s, FMInput *r)
  762. {
  763. char checked;
  764. short i, msize, markchar;
  765.  
  766. msize = CountMItems(myMenus[3]);
  767. for (i=1; i <= msize; i++) {
  768.     GetItemMark(myMenus[3], i, &markchar);
  769.     if (markchar != noMark) {
  770.         checked = 1;
  771.         break;
  772.         }
  773.     }
  774. if (!checked) return(1);
  775. GetItem(myMenus[3], i, s);
  776. UseResFile(resref);
  777. GetFNum(s, &(r->family));
  778. UseResFile(myref);
  779. p2cstr(s);
  780. r->size = fontsize;
  781. r->face = 0;
  782. GetItemMark(myMenus[5], 2, &markchar);
  783. if (markchar != noMark) r->face |= bold; 
  784. GetItemMark(myMenus[5], 3, &markchar);
  785. if (markchar != noMark) r->face |= italic; 
  786. GetItemMark(myMenus[5], 4, &markchar);
  787. if (markchar != noMark) r->face |= underline; 
  788. GetItemMark(myMenus[5], 5, &markchar);
  789. if (markchar != noMark) r->face |= outline; 
  790. GetItemMark(myMenus[5], 6, &markchar);
  791. if (markchar != noMark) r->face |= shadow; 
  792. GetItemMark(myMenus[5], 7, &markchar);
  793. if (markchar != noMark) r->face |= condense; 
  794. GetItemMark(myMenus[5], 8, &markchar);
  795. if (markchar != noMark) r->face |= extend;
  796. r->needBits = true;
  797. r->device = 0;
  798. (r->numer).v = (r->numer).h = (r->denom).v = (r->denom).h = 256;
  799. return(0);
  800. }
  801.  
  802. OSErr openrfile(void)
  803. {
  804. unsigned char *prompt;
  805. FileFilterProcPtr fileFilter;
  806. int numTypes;
  807. SFTypeList typeList;
  808. DlgHookProcPtr dlgHook;
  809. SFReply reply;
  810. pascal Boolean onlyrsrc();
  811.  
  812. prompt = 0;
  813. dlgHook = 0;
  814. fileFilter = onlyrsrc;
  815. numTypes = -1;
  816. SFGetFile(sfgpoint, prompt, fileFilter, numTypes,
  817.     &typeList,dlgHook,&reply);
  818. if (reply.good == 0) return(1);
  819. SetVol(0L, reply.vRefNum);
  820. resref = OpenResFile(&reply.fName);
  821. if (resref == 0) resref = myref;
  822. UseResFile(myref);
  823. return(0);
  824. }
  825.  
  826. pascal Boolean onlyrsrc(FileParam *pb)
  827. {
  828. if (pb->ioFlRLgLen == 0L) return(true);
  829.     else return(0);
  830. }
  831.  
  832. void getfref(void)
  833. {
  834. DlgHookProcPtr dlgHook;
  835. SFReply reply;
  836. OSErr rc;
  837.  
  838. myfref = 0;
  839. dlgHook = 0;
  840. SFPutFile(sfppoint, "\PSave font data in:", "\P", dlgHook, &reply);
  841. if (reply.good == 0) return;
  842. rc = FSDelete(&reply.fName, reply.vRefNum);    /* delete existing file */
  843. rc = Create(&reply.fName, reply.vRefNum, 'MPS ', 'TEXT');
  844. rc = FSOpen(&reply.fName, reply.vRefNum, &myfref);
  845. if (rc != 0) {
  846.     myfref = 0;
  847.     }
  848. }
  849.  
  850. void closefile(void)
  851. {
  852. if (myfref != 0) {
  853.     FSClose(myfref);
  854.     myfref = 0;
  855.     }
  856. }
  857.  
  858. int sizescan(void)
  859. {
  860. unsigned char *p;
  861. short *owtab;
  862. short firstchar, lastchar;
  863. register short i;
  864. unsigned short offset;
  865. char foundmissing;
  866. Rect pRect, destrect;
  867. short vpixsize, hpixsize;
  868. GrafPtr gp;
  869. unsigned char *imageptr;
  870. unsigned long mapoffset;
  871. unsigned char *tp;
  872. CharToGlyphHdr *cmpp;
  873. unsigned long fmt_offset;
  874. CharToGlyphFmt0 *fmt0p;
  875. CharToGlyphFmt6 *fmt6p;
  876. unsigned short startoffset, endoffset;
  877. unsigned char errtext[128];
  878.  
  879. /* Define "missing" flag for each character using font resource */
  880. if (ttfont) {
  881.     mapoffset = gettaboffset(dlgoutput.fontHandle, 'cmap');
  882.     if (mapoffset == 0) {
  883.         showerr("'cmap' table not found in 'sfnt' resource.");
  884.         return(1);
  885.         }
  886.     tp = *(unsigned char **)(dlgoutput.fontHandle);
  887.     tp += mapoffset;
  888.     cmpp = (CharToGlyphHdr *)tp;
  889.     fmt_offset = getfmtoffset(cmpp, 0);
  890.     if (fmt_offset == 0) {
  891.         showerr("Encoding id 0 not found in 'cmap' table.");
  892.         return(2);
  893.         }
  894.     tp += fmt_offset;
  895.     fmt0p = (CharToGlyphFmt0 *)tp;
  896.     foundmissing = 0;
  897.     switch (fmt0p->format) {
  898.         case 0:
  899.                 for (i=0; i < 256; i++) {
  900.                     scandata[i].missing = ((fmt0p->glyphIndexArray)[i] == 0);
  901.                     if (scandata[i].missing) {
  902.                         foundmissing = 1;
  903.                         }
  904.                     }
  905.                 break;
  906.         case 6:
  907.                 fmt6p = (CharToGlyphFmt6 *)tp;
  908.                 startoffset = fmt6p->firstCode;
  909.                 endoffset = startoffset + fmt6p->entryCount - 1;
  910.                 for (i=0; i < 256; i++) {
  911.                     if ((i < startoffset) || (i > endoffset)) {
  912.                         scandata[i].missing = 1;
  913.                         foundmissing = 1;
  914.                         }
  915.                     else {
  916.                         scandata[i].missing =
  917.                             ((fmt6p->glyphIndexArray)[i-startoffset] == 0);                        
  918.                         if (scandata[i].missing) {
  919.                             foundmissing = 1;
  920.                             }
  921.                         }
  922.                     }
  923.                 break;
  924.         default:
  925.                 sprintf(errtext,
  926.                     "Sorry, 'cmap' subtable format %d is not supported.",
  927.                     fmt0p->format);
  928.                 showerr(errtext);
  929.                 return(3);
  930.                 break;
  931.         }
  932.     scandata[256].missing = (foundmissing == 0);
  933.     if (scandata[256].missing) {
  934.         showerr("Unable to draw missing character.  Missing character will be blank");
  935.         }
  936.     }
  937. else {
  938.     firstchar = (*(FontRec **)(dlgoutput.fontHandle))->firstChar;
  939.     lastchar = (*(FontRec **)(dlgoutput.fontHandle))->lastChar;
  940.     p = (unsigned char *)&(*(FontRec **)(dlgoutput.fontHandle))->owTLoc;
  941.     offset = (*(FontRec **)(dlgoutput.fontHandle))->owTLoc;
  942.     p += offset << 1;
  943.     owtab = (short *)p;
  944.  
  945.     foundmissing = 0;
  946.     for (i=0; i < 256; i++) {
  947.         scandata[i].missing = 0;
  948.         if ((i < firstchar) || (i > lastchar)) {
  949.             scandata[i].missing = 1;
  950.             foundmissing = 1;
  951.             }
  952.         else {
  953.             scandata[i].missing = (owtab[i-firstchar] == -1);
  954.             if (scandata[i].missing) foundmissing = 1;
  955.             }
  956.         }
  957.     scandata[256].missing = (foundmissing == 0);
  958.     if (scandata[256].missing) {
  959.         showerr("Unable to draw missing character.  Missing character will be blank");
  960.         }
  961.     }
  962.  
  963. /* define scan information for each character not missing, and for the
  964.    missing character */
  965.  
  966. /* create window to show what we are doing */
  967. if (myWindow != 0) {
  968.     CloseWindow(myWindow);
  969.     myWindow = 0;
  970.     }
  971. vpixsize = hpixsize = 272;
  972. if (bigscreen) {
  973.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/3+9;
  974.     }
  975. else {
  976.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/2+9;
  977.     }
  978. pRect.left = (screenRect.right-screenRect.left-hpixsize)/2-1;
  979. pRect.bottom = pRect.top+vpixsize;
  980. pRect.right = pRect.left+hpixsize;
  981. GetPort(&gp);
  982.  
  983. myWindow = NewWindow((Ptr)&wRecord, &pRect, "\pPass One: Character Sizes",
  984.                      true, noGrowDocProc, (WindowPtr)-1L, false, 0L);
  985.  
  986. /* create image bitmap */
  987. WriteMap.bounds.top = 0;
  988. WriteMap.bounds.left = 0;
  989. WriteMap.bounds.bottom = 256;
  990. WriteMap.bounds.right = 256;
  991. WriteMap.rowBytes = 32;
  992. imageptr = imagebuff;
  993. while ((Size)imageptr%4) imageptr++;
  994. WriteMap.baseAddr = imageptr;
  995.  
  996. /* set-up corresponding GrafPort */
  997. WritePtr = &WritePort;            /* set-up WritePort */
  998. OpenPort(WritePtr);
  999. WritePort.portRect = WriteMap.bounds;
  1000. ClipRect(&WritePort.portRect);
  1001. SetPortBits(&WriteMap);
  1002. EraseRgn(WritePort.visRgn);
  1003. TextFont(dlginput.family);
  1004. TextFace(dlginput.face);
  1005. TextSize(dlginput.size);
  1006.  
  1007. destrect.top = destrect.left = 8;
  1008. destrect.bottom = destrect.right = 264;
  1009. SetPort(myWindow);
  1010. foundmissing = 0;
  1011. drawgrid(1);
  1012.                     /* entire font extent in element 256 */
  1013. scandata[256].image_left = scandata[256].image_top = 256;
  1014. scandata[256].image_right = scandata[256].image_bottom = -1;
  1015. scandata[256].pen_right = 0;
  1016. for (i=0; i < 256; i++) {
  1017.     if (scandata[i].missing) {
  1018.         if (foundmissing) continue;
  1019.         else foundmissing = 1;
  1020.         }
  1021.     SetPort(WritePtr);
  1022.     EraseRect(&WritePort.portRect);
  1023.     MoveTo(64, 192);
  1024.     UseResFile(resref);
  1025.     myDrawChar(i);
  1026.     analyse_char(WriteMap.baseAddr, i);
  1027.     UseResFile(myref);
  1028.     drawgrid(0);
  1029.     SetPort(myWindow);
  1030.     CopyBits(&WritePort.portBits, &(myWindow->portBits),
  1031.             &WritePort.portRect, &destrect, srcCopy, 0L);
  1032.     }
  1033. scandata[256].image_left = scandata[256].image_left - 64;
  1034. scandata[256].image_right = scandata[256].image_right - 64 + 1;
  1035. scandata[256].image_top = 192 - scandata[256].image_top;
  1036. scandata[256].image_bottom = 192 - scandata[256].image_bottom - 1;
  1037. scandata[256].pen_right = scandata[256].pen_right - 64;
  1038. SetPort(gp);
  1039. ClosePort(WritePtr);
  1040. CloseWindow(myWindow);
  1041. myWindow = 0;
  1042. return(0);
  1043. }
  1044.  
  1045. void showextent(void)
  1046. {
  1047. unsigned char s[256];
  1048.  
  1049. sprintf(s,
  1050.  "Image rectange: left = %d, right = %d, bottom = %d, top = %d; maximum width (final pen position) = %d",
  1051. scandata[256].image_left, scandata[256].image_right,
  1052. scandata[256].image_bottom, scandata[256].image_top,
  1053. scandata[256].pen_right);
  1054. showmsg(s);
  1055. }
  1056.  
  1057. void chars2text(void)
  1058. {
  1059. Rect pRect, destrect;
  1060. short vpixsize, hpixsize;
  1061. GrafPtr gp;
  1062. unsigned char *imageptr;
  1063. char foundmissing;
  1064. unsigned char s[256];
  1065. register short i;
  1066.  
  1067.  
  1068. /* output information for each character not missing, and for the
  1069.    missing character */   
  1070.  
  1071. /* outut summary information for font */
  1072. blankline();
  1073. sprintf(s, "Extent information for entire font:");
  1074. dlgline(s);
  1075. sprintf(s, "Image rectange: left = %d, right = %d, bottom = %d, top = %d",
  1076. scandata[256].image_left, scandata[256].image_right,
  1077. scandata[256].image_bottom, scandata[256].image_top);
  1078. dlgline(s);
  1079. sprintf(s, "Width (final pen position) = %d", scandata[256].pen_right);
  1080. dlgline(s);
  1081.  
  1082. /* create window to show what we are doing */
  1083. if (myWindow != 0) {
  1084.     CloseWindow(myWindow);
  1085.     myWindow = 0;
  1086.     }
  1087. vpixsize = hpixsize = 272;
  1088. if (bigscreen) {
  1089.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/3+9;
  1090.     }
  1091. else {
  1092.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/2+9;
  1093.     }
  1094. pRect.left = (screenRect.right-screenRect.left-hpixsize)/2-1;
  1095. pRect.bottom = pRect.top+vpixsize;
  1096. pRect.right = pRect.left+hpixsize;
  1097. GetPort(&gp);
  1098.  
  1099. myWindow = NewWindow((Ptr)&wRecord, &pRect, "\pPass Two: Bitmap Imaging",
  1100.                      true, noGrowDocProc, (WindowPtr)-1L, false, 0L);
  1101.  
  1102. /* create image bitmap */
  1103. WriteMap.bounds.top = 0;
  1104. WriteMap.bounds.left = 0;
  1105. WriteMap.bounds.bottom = 256;
  1106. WriteMap.bounds.right = 256;
  1107. WriteMap.rowBytes = 32;
  1108. imageptr = imagebuff;
  1109. while ((Size)imageptr%4) imageptr++;
  1110. WriteMap.baseAddr = imageptr;
  1111.  
  1112. /* set-up corresponding GrafPort */
  1113. WritePtr = &WritePort;            /* set-up WritePort */
  1114. OpenPort(WritePtr);
  1115. WritePort.portRect = WriteMap.bounds;
  1116. ClipRect(&WritePort.portRect);
  1117. SetPortBits(&WriteMap);
  1118. EraseRgn(WritePort.visRgn);
  1119. TextFont(dlginput.family);
  1120. TextFace(dlginput.face);
  1121. TextSize(dlginput.size);
  1122.  
  1123. destrect.top = destrect.left = 8;
  1124. destrect.bottom = destrect.right = 264;
  1125. SetPort(myWindow);
  1126. foundmissing = 0;
  1127. drawgrid(1);
  1128. newpage = CHARSPERPAGE;
  1129. for (i=0; i < 256; i++) {
  1130.     if (scandata[i].missing) {
  1131.         if (foundmissing) continue;
  1132.         else foundmissing = 1;
  1133.         }
  1134.     SetPort(WritePtr);
  1135.     EraseRect(&WritePort.portRect);
  1136.     MoveTo(64, 192);
  1137.     UseResFile(resref);
  1138.     myDrawChar(i);
  1139.     output_char(WriteMap.baseAddr, i);
  1140.     newpage++;
  1141.     UseResFile(myref);
  1142.     drawgrid(0);
  1143.     SetPort(myWindow);
  1144.     CopyBits(&WritePort.portBits, &(myWindow->portBits),
  1145.             &WritePort.portRect, &destrect, srcCopy, 0L);
  1146.     }
  1147. SetPort(gp);
  1148. ClosePort(WritePtr);
  1149. CloseWindow(myWindow);
  1150. myWindow = 0;
  1151. }
  1152.  
  1153. void analyse_char(unsigned char *addr, short charcode)
  1154. {
  1155. unsigned char *lineptr;
  1156. imageinfo *ifp, *ifps;
  1157. Point pt;
  1158. register short line, byte;
  1159. short leftbyte, rightbyte, bitpos;
  1160.  
  1161. lineptr = addr;
  1162. ifp = scandata + charcode;
  1163. ifps = scandata + 256;        /* font summary info */
  1164. ifp->image_left = ifp->image_top = 256;
  1165. ifp->image_right = ifp->image_bottom = -1;
  1166. GetPen(&pt);
  1167. ifp->pen_right = pt.h - 64;
  1168. if (ifps->pen_right < pt.h) ifps->pen_right = pt.h;
  1169. ifp->blank = 1;
  1170. for (line = 0; line < 256; line++) {
  1171.     leftbyte = -1;
  1172.     for (byte = 0; byte < 32; byte++) {
  1173.     if (lineptr[byte] != 0) {
  1174.         leftbyte = byte;
  1175.         break;
  1176.         }
  1177.     }
  1178.     if (leftbyte >= 0) {
  1179.         ifp->blank = 0;
  1180.         if (line < ifp->image_top) ifp->image_top = line;
  1181.         if (line > ifp->image_bottom) ifp->image_bottom = line;
  1182.         if (line < ifps->image_top) ifps->image_top = line;
  1183.         if (line > ifps->image_bottom) ifps->image_bottom = line;
  1184.         bitpos = leftbyte*8 + cvtleft(lineptr[leftbyte]);
  1185.         if (ifp->image_left > bitpos) ifp->image_left = bitpos;
  1186.         if (ifps->image_left > bitpos) ifps->image_left = bitpos;
  1187.         rightbyte = -1;
  1188.         for (byte = 31; byte >= 0; byte--) {
  1189.             if (lineptr[byte] != 0) {
  1190.                 rightbyte = byte;
  1191.                 break;
  1192.                 }
  1193.             }
  1194.         if (rightbyte >= 0) {
  1195.             bitpos = rightbyte*8 + cvtright(lineptr[rightbyte]);
  1196.             if (ifp->image_right < bitpos) ifp->image_right = bitpos;
  1197.             if (ifps->image_right < bitpos) ifps->image_right = bitpos;
  1198.             }
  1199.         }
  1200.     lineptr += 32;
  1201.     }
  1202. if (ifp->blank == 0) {
  1203.     ifp->image_left = ifp->image_left - 64;
  1204.     ifp->image_right = ifp->image_right - 64 + 1;
  1205.     ifp->image_top = 192 - ifp->image_top;
  1206.     ifp->image_bottom = 192 - ifp->image_bottom - 1;
  1207.     }
  1208. }
  1209.  
  1210. int getbit(unsigned char *p, short n)
  1211. {
  1212. register short byte, mask;
  1213.  
  1214. byte = n/8;
  1215. mask = 0x01 << (7-n%8);
  1216. if (p[byte] & mask) return('*');
  1217. else return('.');
  1218. }
  1219.  
  1220. int cvtleft(int i)
  1221. {
  1222. if (i & 0x80) return(0);
  1223. if (i & 0x40) return(1);
  1224. if (i & 0x20) return(2);
  1225. if (i & 0x10) return(3);
  1226. if (i & 0x08) return(4);
  1227. if (i & 0x04) return(5);
  1228. if (i & 0x02) return(6);
  1229. return(7);
  1230. }
  1231.  
  1232. int cvtright(int i)
  1233. {
  1234. if (i & 0x01) return(7);
  1235. if (i & 0x02) return(6);
  1236. if (i & 0x04) return(5);
  1237. if (i & 0x08) return(4);
  1238. if (i & 0x10) return(3);
  1239. if (i & 0x20) return(2);
  1240. if (i & 0x40) return(1);
  1241. return(0);
  1242. }
  1243.  
  1244. output_char(unsigned char *addr, short charcode)
  1245. {
  1246. unsigned char s[256];
  1247. imageinfo *ifp;
  1248. register short i, line, bit;
  1249. unsigned char *lineptr;
  1250.  
  1251. ifp = scandata + charcode;
  1252. blankline();
  1253. if (ifp->missing) {
  1254.     sprintf(s, "Character: Missing character");
  1255.     }
  1256. else {
  1257.     if ((((charcode >= 0x20) && (charcode <= 0x7e)) ||
  1258.          (charcode >= 0x80)) && stdfont) {
  1259.         sprintf(s, "Character: x'%02x' (%c)", charcode, charcode);
  1260.         }
  1261.     else {
  1262.         sprintf(s, "Character: x'%02x'", charcode);
  1263.         }
  1264.     }
  1265. if (ifp->blank) strcat(s, " [all blank]");
  1266. dlgline(s);
  1267. if (ifp->blank == 0) {
  1268.     sprintf(s, "Image rectange: left = %d, right = %d, bottom = %d, top = %d",
  1269.     ifp->image_left, ifp->image_right, ifp->image_bottom, ifp->image_top);
  1270.     dlgline(s);
  1271.     }
  1272. sprintf(s, "Width (final pen position) = %d", ifp->pen_right);
  1273. dlgline(s);
  1274. if (ifp->blank) return;
  1275.  
  1276. s[0] = s[1] = ' ';
  1277. if (cc) s[2] = 0xcc;
  1278. else s[2] = '+';
  1279. for (i = scandata[256].image_left; i < scandata[256].image_right; i++) {
  1280.     if (cc) s[i+3-scandata[256].image_left] = 0xbd;
  1281.     else s[i+3-scandata[256].image_left] = '-';
  1282.     }
  1283. if (cc) s[i+3-scandata[256].image_left] = 0xde;
  1284. else s[i+3-scandata[256].image_left] = '+';
  1285. s[i+4-scandata[256].image_left] = '\0';
  1286. dlgline(s);
  1287.  
  1288. lineptr = addr;
  1289. lineptr += (192 - scandata[256].image_top)*32;
  1290. for (line = 192 - scandata[256].image_top;
  1291.      line < 192 - scandata[256].image_bottom; line++) {
  1292.      i = 191 - line;
  1293.      if (i > 9) {
  1294.          s[0] = i/10 + '0';
  1295.         s[1] = i%10 + '0';
  1296.         }
  1297.     else if (i >= 0) {
  1298.         s[0] = ' ';
  1299.         s[1] = i + '0';
  1300.         }
  1301.     else {
  1302.         s[0] = '-';
  1303.         s[1] = (-i)%10 + '0';
  1304.         }
  1305.     if (cc) s[2] = 0xae;
  1306.     else s[2] = '|';
  1307.     for (bit = scandata[256].image_left+64; bit < scandata[256].image_right+64;
  1308.         bit++) {
  1309.         s[bit+3-scandata[256].image_left-64] = getbit(lineptr, bit);
  1310.         }
  1311.     if (cc) s[scandata[256].image_right-scandata[256].image_left+3] = 0xae;
  1312.     else s[scandata[256].image_right-scandata[256].image_left+3] = '|';
  1313.     s[scandata[256].image_right-scandata[256].image_left+4] = '\0';
  1314.     dlgline(s);
  1315.     lineptr += 32;
  1316.     }
  1317.  
  1318. s[0] = s[1] = ' ';
  1319. if (cc) s[2] = 0xda;
  1320. else s[2] = '+';
  1321. for (i = scandata[256].image_left; i < scandata[256].image_right; i++) {
  1322.     if (cc) s[i+3-scandata[256].image_left] = 0xbd;
  1323.     else s[i+3-scandata[256].image_left] = '-';
  1324.     }
  1325. if (cc) s[i+3-scandata[256].image_left] = 0x86;
  1326. else s[i+3-scandata[256].image_left] = '+';
  1327. s[i+4-scandata[256].image_left] = '\0';
  1328. dlgline(s);
  1329.  
  1330. s[0] = s[1] = s[2] = ' ';
  1331. for (i = scandata[256].image_left; i < scandata[256].image_right; i++) {
  1332.     if (i < 0) s[i+3-scandata[256].image_left] =  (-i)%10 + '0';
  1333.     else s[i+3-scandata[256].image_left] = i%10 + '0';
  1334.     }
  1335. s[i+3-scandata[256].image_left] = '\0';
  1336. dlgline(s);
  1337.  
  1338. if ((scandata[256].image_left < 0) || 
  1339.     (scandata[256].image_right > 10)) {     
  1340.     s[0] = s[1] = s[2] = ' ';
  1341.     for (i = scandata[256].image_left; i < scandata[256].image_right; i++) {
  1342.         if (i < 0) s[i+3-scandata[256].image_left] = '-';
  1343.         else if (i > 9) s[i+3-scandata[256].image_left] = i/10 + '0';
  1344.         else s[i+3-scandata[256].image_left] = ' ';
  1345.         }
  1346.     s[i+3-scandata[256].image_left] = '\0';
  1347.     dlgline(s);
  1348.     }
  1349. }
  1350.  
  1351. void showerr(unsigned char *s)
  1352. {
  1353. static char nullstr[1] = {0};
  1354.  
  1355. c2pstr(s);
  1356. ParamText(s, nullstr, nullstr, nullstr);
  1357. p2cstr(s);
  1358. StopAlert(256, 0L);
  1359. ParamText(nullstr, nullstr, nullstr, nullstr);
  1360. }
  1361.  
  1362. void showmsg(unsigned char *s)
  1363. {
  1364. static char nullstr[1] = {0};
  1365.  
  1366. c2pstr(s);
  1367. ParamText(s, nullstr, nullstr, nullstr);
  1368. p2cstr(s);
  1369. NoteAlert(260, 0L);
  1370. ParamText(nullstr, nullstr, nullstr, nullstr);
  1371. }
  1372.  
  1373. void ctralrt(short a)
  1374.                 /* a is alert number */
  1375. {
  1376. Handle reshnd;
  1377. struct Rect * rptr;
  1378. short scrhsize, scrvsize;
  1379. short ahsize, avsize;
  1380.  
  1381. CouldAlert(a);        /* read alert into memory and make unpurgeable */
  1382. reshnd = GetResource('ALRT', a);
  1383. if (reshnd == 0) return;
  1384. rptr = (struct Rect *)*reshnd;
  1385. scrhsize = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
  1386. scrvsize = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
  1387. ahsize = rptr->right - rptr->left;
  1388. avsize = rptr->bottom - rptr->top;
  1389. rptr->top = (scrvsize-avsize)/3;
  1390. rptr->left = (scrhsize-ahsize)/2;
  1391. rptr->bottom = rptr->top + avsize;
  1392. rptr->right = rptr->left + ahsize;
  1393. }
  1394.  
  1395. void aboutdlg(void)
  1396. {
  1397. DialogPtr dlgptr;
  1398. short itemHit;
  1399. unsigned char **version;
  1400. static char nullstr[1] = {0};
  1401.  
  1402. dlgptr = GetNewDialog(257, (Ptr)0L, (WindowPtr)-1L);
  1403. if (bigscreen) ctrwindow(dlgptr);
  1404. version = GetResource('BTFT', 0);
  1405. if (version == 0L) {
  1406.     DisposDialog(dlgptr);
  1407.     return;
  1408.     }
  1409. ParamText((*version), nullstr, nullstr, nullstr);
  1410. ShowWindow(dlgptr);
  1411.  
  1412. /* frame the default selection */
  1413. framedflt(dlgptr);
  1414.  
  1415. ModalDialog(0L, &itemHit);
  1416. DisposDialog(dlgptr);
  1417. ParamText(nullstr, nullstr, nullstr, nullstr);
  1418. }
  1419.  
  1420. void fsizedlg(void)
  1421. {
  1422. DialogPtr dlgptr;
  1423. short itemHit, lasthit;
  1424. short gtype;
  1425. Handle gitem;
  1426. Rect gbox;
  1427. short fs;
  1428. unsigned char result[256], newnum[10];
  1429. short i;
  1430.  
  1431. dlgptr = GetNewDialog(258, (Ptr)0L, (WindowPtr)-1L);
  1432. ctrwindow(dlgptr);
  1433. ShowWindow(dlgptr);
  1434.  
  1435. /* frame the default selection */
  1436. framedflt(dlgptr);
  1437.  
  1438. fs = fontsize;
  1439. setfnum(dlgptr, fs);
  1440. SelIText(dlgptr, 4, 0, 32767);
  1441. itemHit = 99;
  1442. lasthit = 99;
  1443. while (1) {
  1444.     ModalDialog(0L, &itemHit);
  1445.     if ((lasthit == 4) && (itemHit != 4)) { 
  1446.         GetDItem(dlgptr, 4, >ype, &gitem, &gbox);
  1447.         GetIText(gitem, result);
  1448.         p2cstr(result);
  1449.         fs = atoi(result);
  1450.         if (fs <= 0) fs = 9;
  1451.         }
  1452.     if (itemHit < 3) break;
  1453.     switch(itemHit) {
  1454.         case 4:
  1455.                     GetDItem(dlgptr, itemHit, >ype, &gitem, &gbox);
  1456.                     GetIText(gitem, result);
  1457.                     p2cstr(result);
  1458.                     i = 0;
  1459.                     while (result[i] != 0) {
  1460.                         if ((result[i] != 0x20) && ((result[i] < 0x30) ||
  1461.                             (result[i] > 0x39))) {
  1462.                             SysBeep(1);
  1463.                             break;
  1464.                             }
  1465.                         i++;
  1466.                         }
  1467.                     i = atoi(result) % 1000;
  1468.                     if (i == 0) {
  1469.                         newnum[0] = 0;
  1470.                         }
  1471.                     else {
  1472.                         sprintf(newnum, "%d", i);
  1473.                         }
  1474.                     if (strcmp(result, newnum) != 0) {
  1475.                         c2pstr(newnum);
  1476.                         SetIText(gitem, newnum);
  1477.                         }
  1478.                     break;
  1479.         default:
  1480.                     break;
  1481.         }
  1482.     lasthit = itemHit;
  1483.     }
  1484. DisposDialog(dlgptr);
  1485. if (itemHit == 1) fontsize = fs;
  1486. }
  1487.  
  1488. void setfnum(DialogPtr dlgptr, short fs)
  1489. {
  1490. short gtype;
  1491. Handle gitem;
  1492. Rect gbox;
  1493. unsigned char result[256], newnum[10];
  1494.  
  1495. GetDItem(dlgptr, 4, >ype, &gitem, &gbox);
  1496. GetIText(gitem, result);
  1497. p2cstr(result);
  1498. sprintf(newnum, "%d", fs);
  1499. if (strcmp(result, newnum) != 0) {
  1500.     c2pstr(newnum);
  1501.     SetIText(gitem, newnum);
  1502.     }
  1503. }
  1504.  
  1505. void showfrec(void)
  1506. {
  1507. DialogPtr dlgptr;
  1508. short itemHit;
  1509. short gtype;
  1510. Handle gitem;
  1511. Rect mybox;
  1512. pascal void (*myitem) ();
  1513. pascal void frectext();
  1514.  
  1515. if (fileflag == 0) {
  1516.     dlgptr = GetNewDialog(259, (Ptr)0L, (WindowPtr)-1L);
  1517.     if (bigscreen) ctrwindow(dlgptr);
  1518.  
  1519.     /* define routine to draw user item */
  1520.     GetDItem(dlgptr, 2, >ype, &gitem, &mybox);
  1521.     myitem = frectext;
  1522.     SetDItem(dlgptr, 2, gtype, (Handle)myitem, &mybox);
  1523.  
  1524.     ShowWindow(dlgptr);
  1525.  
  1526.     /* frame the default selection */
  1527.     framedflt(dlgptr);
  1528.  
  1529.     ModalDialog(0L, &itemHit);
  1530.     DisposDialog(dlgptr);
  1531.     }
  1532. else {
  1533.     showtext((WindowPtr)0L, 0);
  1534.     }
  1535. }
  1536.  
  1537. pascal void frectext(WindowPtr dlgwindow, short item)
  1538. {
  1539. showtext(dlgwindow, item);
  1540. }
  1541.  
  1542. void showtext(WindowPtr dlgwindow, short item)
  1543. {
  1544. GrafPtr gp;
  1545. unsigned char s[256];
  1546. float d, n;
  1547.  
  1548. if (dlgwindow != 0) {
  1549.     gp = (GrafPtr)item;        /* avoid "not used" warning message */
  1550.     GetPort(&gp);
  1551.     SetPort(dlgwindow);
  1552.     TextFont(3);            /* Geneva */
  1553.     TextSize(12);            /* 9 and 12-point are always available */
  1554.     dlgxpos = 5;
  1555.     dlgypos = -4;
  1556.     }
  1557. sprintf(s, "Font name = %s", dlgfname);
  1558. dlgline(s);
  1559. sprintf(s, "Font number = %d", dlginput.family);
  1560. dlgline(s);
  1561. if (dlgwindow != 0) {
  1562.     TextFace(bold);
  1563.     }
  1564. else {
  1565.     blankline();
  1566.     }
  1567. sprintf(s, "Font Output Record:");
  1568. dlgline(s);
  1569. if (dlgwindow != 0) {
  1570.     TextFace(0);
  1571.     }
  1572. sprintf(s, "Error number = %d", dlgoutput.errNum);
  1573. dlgline(s);
  1574. sprintf(s, "Bold factor = %d", dlgoutput.boldPixels);
  1575. dlgline(s);
  1576. sprintf(s, "Italic factor = %d", dlgoutput.italicPixels);
  1577. dlgline(s);
  1578. sprintf(s, "Underline offset = %d", dlgoutput.ulOffset);
  1579. dlgline(s);
  1580. sprintf(s, "Underline shadow = %d", dlgoutput.ulShadow);
  1581. dlgline(s);
  1582. sprintf(s, "Underline thickness = %d", dlgoutput.ulThick);
  1583. dlgline(s);
  1584. sprintf(s, "Shadow factor = %d", dlgoutput.shadowPixels);
  1585. dlgline(s);
  1586. sprintf(s, "Style width (extra) = %d", dlgoutput.extra);
  1587. dlgline(s);
  1588. sprintf(s, "Ascent = %d", dlgoutput.ascent);
  1589. dlgline(s);
  1590. sprintf(s, "Descent = %d", dlgoutput.descent);
  1591. dlgline(s);
  1592. sprintf(s, "Maximum width = %d", dlgoutput.widMax);
  1593. dlgline(s);
  1594. sprintf(s, "Leading = %d", dlgoutput.leading);
  1595. dlgline(s);
  1596. sprintf(s, "Styles to apply = %x", dlgoutput.unused);
  1597. dlgline(s);
  1598. n = dlgoutput.numer.h;
  1599. d = dlgoutput.denom.h;
  1600. sprintf(s, "Horiz. scaling = %f", n/d);
  1601. dlgline(s);
  1602. n = dlgoutput.numer.v;
  1603. d = dlgoutput.denom.v;
  1604. sprintf(s, "Vert. scaling = %f", n/d);
  1605. dlgline(s);
  1606.  
  1607. if (dlgwindow != 0) {
  1608.     dlgxpos = 210;
  1609.     dlgypos = -4;
  1610.     }
  1611. sprintf(s, "Font size = %d", dlginput.size);
  1612. dlgline(s);
  1613. sprintf(s, "Styles = %x", dlginput.face);
  1614. dlgline(s);
  1615. if (dlgoutput.fontHandle == 0) {
  1616.     if (dlgwindow != 0) {
  1617.         SetPort(gp);
  1618.         }
  1619.     return;
  1620.     }
  1621. if (ttfont) {
  1622.     showfheader(s, dlgwindow);
  1623.     }
  1624. else {
  1625.     showresrecord(s, dlgwindow);
  1626.     }
  1627. strcpy(s, "");
  1628. dlgline(s);
  1629. strcpy(s, "Imaging type: ");
  1630. if (ttfont) {
  1631.     strcat(s, "TrueType™");
  1632.     }
  1633. else if (atmfont) {
  1634.     strcat (s, "ATM");
  1635.     }
  1636. else {
  1637.     strcat(s, "Bitmap");
  1638.     }
  1639. dlgline(s);
  1640. if (dlgwindow != 0) {
  1641.     SetPort(gp);
  1642.     }
  1643. }
  1644.  
  1645. void showresrecord(unsigned char *s, WindowPtr dlgwindow)
  1646. {
  1647. if (dlgwindow != 0) {
  1648.     TextFace(bold);
  1649.     }
  1650. else {
  1651.     blankline();
  1652.     }
  1653. sprintf(s, "Font Resource Record:");
  1654. dlgline(s);
  1655. if (dlgwindow != 0) {
  1656.     TextFace(0);
  1657.     }
  1658. sprintf(s, "Font type = %x", 
  1659.     (unsigned short)(*(FontRec **)(dlgoutput.fontHandle))->fontType);
  1660. dlgline(s);
  1661. sprintf(s, "First character = %x", 
  1662.     (*(FontRec **)(dlgoutput.fontHandle))->firstChar);
  1663. dlgline(s);
  1664. sprintf(s, "Last character = %x", 
  1665.     (*(FontRec **)(dlgoutput.fontHandle))->lastChar);
  1666. dlgline(s);
  1667. sprintf(s, "Maximum width = %d", 
  1668.     (*(FontRec **)(dlgoutput.fontHandle))->widMax);
  1669. dlgline(s);
  1670. sprintf(s, "Negative max. kern = %d", 
  1671.     (*(FontRec **)(dlgoutput.fontHandle))->kernMax);
  1672. dlgline(s);
  1673. sprintf(s, "Negative descent = %d", 
  1674.     (*(FontRec **)(dlgoutput.fontHandle))->nDescent);
  1675. dlgline(s);
  1676. sprintf(s, "Rectangle width = %d", 
  1677.     (*(FontRec **)(dlgoutput.fontHandle))->fRectWidth);
  1678. dlgline(s);
  1679. sprintf(s, "Rectangle height = %d", 
  1680.     (*(FontRec **)(dlgoutput.fontHandle))->fRectHeight);
  1681. dlgline(s);
  1682. sprintf(s, "Offset table offset = %d", 
  1683.     (*(FontRec **)(dlgoutput.fontHandle))->owTLoc);
  1684. dlgline(s);
  1685. sprintf(s, "Ascent = %d", 
  1686.     (*(FontRec **)(dlgoutput.fontHandle))->ascent);
  1687. dlgline(s);
  1688. sprintf(s, "Descent = %d", 
  1689.     (*(FontRec **)(dlgoutput.fontHandle))->descent);
  1690. dlgline(s);
  1691. sprintf(s, "Leading = %d", 
  1692.     (*(FontRec **)(dlgoutput.fontHandle))->leading);
  1693. dlgline(s);
  1694. sprintf(s, "Row words = %d", 
  1695.     (*(FontRec **)(dlgoutput.fontHandle))->rowWords);
  1696. dlgline(s);
  1697. }
  1698.  
  1699. void showfheader(unsigned char *s, WindowPtr dlgwindow)
  1700. {
  1701. unsigned long hdroffset;
  1702. unsigned char *p;
  1703. fontheader *fhp;
  1704. unsigned char datestr[256];
  1705. unsigned char timestr[256];
  1706. float f;
  1707.  
  1708. hdroffset = gettaboffset(dlgoutput.fontHandle, 'head');
  1709. if (hdroffset == 0) return; 
  1710. p = *(unsigned char **)(dlgoutput.fontHandle);
  1711. p += hdroffset;
  1712. fhp = (fontheader *)p;
  1713. if (dlgwindow != 0) {
  1714.     TextFace(bold);
  1715.     }
  1716. else {
  1717.     blankline();
  1718.     }
  1719. sprintf(s, "'sfnt' Font Header:");
  1720. dlgline(s);
  1721. if (dlgwindow != 0) {
  1722.     TextFace(0);
  1723.     }
  1724. f = (fhp->version & 0x0000ffff)/65536.0;
  1725. f += fhp->version >> 16;
  1726. sprintf(s, "Header version = %.2f", f);
  1727. dlgline(s);
  1728. f = (fhp->fontRevision & 0x0000ffff)/65536.0;
  1729. f += fhp->fontRevision >> 16;
  1730. sprintf(s, "Font revision = %.2f", f);
  1731. dlgline(s);
  1732. sprintf(s, "Flags = %x", fhp->flags);
  1733. dlgline(s);
  1734. sprintf(s, "Units per em = %d", fhp->unitsPerEm);
  1735. dlgline(s);
  1736. IUDateString(fhp->created, shortDate, datestr);
  1737. p2cstr(datestr);
  1738. IUTimeString(fhp->created, false, timestr);
  1739. p2cstr(timestr);
  1740. sprintf(s, "Created: %s %s", datestr, timestr);
  1741. dlgline(s);
  1742. IUDateString(fhp->modified, shortDate, datestr);
  1743. p2cstr(datestr);
  1744. IUTimeString(fhp->modified, false, timestr);
  1745. p2cstr(timestr);
  1746. sprintf(s, "Modified: %s %s", datestr, timestr);
  1747. dlgline(s);
  1748. sprintf(s, "xMin = %d", fhp->xMin);
  1749. dlgline(s);
  1750. sprintf(s, "yMin = %d", fhp->yMin);
  1751. dlgline(s);
  1752. sprintf(s, "xMax = %d", fhp->xMax);
  1753. dlgline(s);
  1754. sprintf(s, "yMax = %d", fhp->yMax);
  1755. dlgline(s);
  1756. sprintf(s, "Mac style = %x", fhp->macStyle);
  1757. dlgline(s);
  1758. sprintf(s, "Smallest readable size = %d", fhp->lowestRecPPEM);
  1759. dlgline(s);
  1760. sprintf(s, "Font direction hint = %d", fhp->fontDirectionHint);
  1761. dlgline(s);
  1762. }
  1763.  
  1764. unsigned long gettaboffset(Handle fh, unsigned long tag)
  1765. {
  1766. unsigned short i, tablecount;
  1767. unsigned char *p;
  1768. TableDirectory *tdp;
  1769.  
  1770. tablecount = (*(fontOffsetTable **)(fh))->numTables;
  1771. p = *(unsigned char **)(fh);
  1772. p += sizeof(fontOffsetTable);
  1773. tdp = (TableDirectory *)p;
  1774. for (i = 0; i < tablecount; i++) {
  1775.     if (tdp->tag == tag) return(tdp->offset);
  1776.     p += sizeof(TableDirectory);
  1777.     tdp = (TableDirectory *)p;
  1778.     }
  1779. return(0);    /* 0 = tag not found */
  1780. }
  1781.  
  1782. unsigned long getfmtoffset(CharToGlyphHdr *cmpp, short format)
  1783. {
  1784. unsigned short i, tablecount;
  1785. unsigned char *p;
  1786. CharToGlyphDir *cgdp;
  1787.  
  1788. tablecount = cmpp->numTables;
  1789. p = (unsigned char *)cmpp;
  1790. p += sizeof(CharToGlyphHdr);
  1791. cgdp = (CharToGlyphDir *)p;
  1792. for (i = 0; i < tablecount; i++) {
  1793.     if (cgdp->encodingId == format) return(cgdp->offset);
  1794.     p += sizeof(CharToGlyphDir);
  1795.     cgdp = (CharToGlyphDir *)p;
  1796.     }
  1797. return(0);    /* 0 = tag not found */
  1798. }
  1799.  
  1800. void myDrawChar(short ch)
  1801. {
  1802. struct {
  1803.     unsigned char *text;
  1804.     short length;
  1805.     FixedMatrix *matrix;
  1806.     } showparms;
  1807. unsigned char s[1];
  1808. FixedMatrix m;
  1809.  
  1810. if (atmfont) {    /* could use DrawChar, but using ATM routine allows */
  1811.                 /* possible modifications to rotate, stretch, etc.    */
  1812.     s[0] = ch;
  1813.     m.a = (Fixed) (dlginput.size*65536.0+0.5);
  1814.     m.b = (Fixed) 0.;
  1815.     m.c = (Fixed) 0.;
  1816.     m.d = (Fixed) (-dlginput.size*65536.0+0.5);
  1817.     m.tx = (Fixed) 0.;
  1818.     m.ty = (Fixed) 0.;
  1819.     showparms.text = s;
  1820.     showparms.length = 1;
  1821.     showparms.matrix = &m;
  1822.     (*procs.showText)(showparms);
  1823.     MoveTo(64 + (m.tx >> 16), 192);
  1824.     }
  1825. else {
  1826.     DrawChar(ch);
  1827.     }
  1828. }
  1829.  
  1830. void dlgline(unsigned char *s)
  1831. {
  1832. long l;
  1833. static unsigned char nl[1] = {'\n'};
  1834. static unsigned char blank[1] = {0x20};
  1835. static unsigned char eject[1] = {'1'};
  1836.  
  1837. if (fileflag == 0) {
  1838.     dlgypos += 14;
  1839.     MoveTo(dlgxpos, dlgypos);
  1840.     c2pstr(s);
  1841.     DrawString(s);
  1842.     }
  1843. else {
  1844.     if (cc) {
  1845.         if (newpage == CHARSPERPAGE) {
  1846.             l = 1;
  1847.             FSWrite(myfref, &l, eject);
  1848.             newpage = 0;
  1849.             }
  1850.         else {
  1851.             l = 1;
  1852.             FSWrite(myfref, &l, blank);
  1853.             }
  1854.         }
  1855.     l = strlen(s);
  1856.     FSWrite(myfref, &l, s);
  1857.     l = 1;
  1858.     FSWrite(myfref, &l, nl);
  1859.     }
  1860. }
  1861.  
  1862. void blankline(void)
  1863. {
  1864. long l;
  1865. static char nl[1] = {'\n'};
  1866.     
  1867. l = 1;
  1868. FSWrite(myfref, &l, nl);
  1869. }
  1870.  
  1871. int newrscfile(void)        /* create new resource file for font resources */
  1872. {
  1873. DlgHookProcPtr dlgHook;
  1874. SFReply reply;
  1875. OSErr rc;
  1876. unsigned char errtext[276];
  1877.  
  1878. dlgHook = 0;
  1879. sprintf(errtext, "%s %d", dlgfname, dlginput.size);
  1880. c2pstr(errtext);
  1881. SFPutFile(sfppoint, "\PNew font file:",
  1882.              errtext, dlgHook, &reply);
  1883. if (reply.good == 0) return(1);
  1884. memcpy(rscfname, &reply.fName, 64);
  1885. rscvrefnum = reply.vRefNum;
  1886. rc = FSDelete(rscfname, rscvrefnum);        /* delete existing file */
  1887. rc = Create(rscfname, rscvrefnum, 'DMOV', 'FFIL');
  1888. if (rc != 0) {
  1889.     sprintf(errtext, "Error %d creating output file.", rc);
  1890.     showerr(errtext);
  1891.     return(2);
  1892.     }
  1893. GetVol(errtext, &currvol);
  1894. SetVol(0L, rscvrefnum);
  1895. CreateResFile(rscfname);
  1896. rfile = OpenResFile(rscfname);
  1897. if (rfile == -1) {
  1898.     FSDelete(rscfname, rscvrefnum);
  1899.     SetVol(0L, currvol);
  1900.     sprintf(errtext, "Error %d opening resource file", ResError());
  1901.     showerr(errtext);
  1902.     return(3);
  1903.     }
  1904. else {
  1905.     UseResFile(myref);
  1906.     return(0);
  1907.     }
  1908. }
  1909.  
  1910. int addfond(void)
  1911. {
  1912. Size fondsize;
  1913. unsigned short resattr;
  1914. OSErr rc;
  1915. unsigned char errtext[256];
  1916. unsigned char *fondptr;
  1917. FamRec *fr;
  1918. FontAssoc *fa;
  1919. AsscEntry *ae;
  1920. short i;
  1921. char foundmissing;
  1922.  
  1923.  
  1924. /* get handle to data to write out */
  1925. fondsize = sizeof(FamRec) + sizeof(FontAssoc) + sizeof(AsscEntry);
  1926. fondhandle = NewHandle(fondsize);
  1927. if (fondhandle == 0) {
  1928.     sprintf(errtext, "Out of memory allocating FOND resource");
  1929.     showerr(errtext);
  1930.     return(1);
  1931.     }
  1932.                     /* initialize all fields to zero */
  1933. memset(*fondhandle, 0, fondsize);
  1934.     
  1935. fondptr = *fondhandle;
  1936. fr = (FamRec *)fondptr;
  1937. fr ->ffFlags = 0x8000;        /* assume fixed-width */
  1938. foundmissing = 0;
  1939. for (i=0; i < 256; i++) {
  1940.     if (scandata[i].missing) {
  1941.         if (foundmissing) continue;
  1942.         else foundmissing = 1;
  1943.         }
  1944.     if (scandata[i].pen_right != scandata[256].pen_right) {
  1945.         fr->ffFlags = 0;    /* reset if a different width */
  1946.         break;
  1947.         }
  1948.     }
  1949. fr->ffFlags |= 0x6000;        /* no fractional width table */
  1950. fr->ffFamID = dlginput.family;
  1951. fr->ffVersion = 2;
  1952.  
  1953. fondptr += sizeof(FamRec);
  1954. fa = (FontAssoc *)fondptr;
  1955. fa->numAssoc = 0;            /* number of entries - 1 */
  1956.  
  1957. fondptr += sizeof(FontAssoc);
  1958. ae = (AsscEntry *)fondptr;
  1959. ae->fontSize = dlginput.size;
  1960. ae->fontStyle = dlginput.face;
  1961. ae->fontID = NFNTID;
  1962.  
  1963. c2pstr(dlgfname);
  1964. UseResFile(rfile);
  1965. AddResource(fondhandle, 'FOND', dlginput.family, dlgfname);
  1966. rc = ResError();
  1967. UseResFile(myref);
  1968. p2cstr(dlgfname);
  1969. if (rc) {
  1970.     sprintf(errtext, "Error %d adding resource to file", rc);
  1971.     showerr(errtext);
  1972.     return(2);
  1973.     }
  1974.  
  1975. resattr = GetResAttrs(fondhandle);
  1976. if (rc = ResError()) {
  1977.     sprintf(errtext, "Error %d getting resource attributes", rc);
  1978.     showerr(errtext);
  1979.     return(3);
  1980.     }
  1981.  
  1982. resattr |= resPurgeable;
  1983.  
  1984. SetResAttrs(fondhandle, resattr);
  1985. if (rc = ResError()) {
  1986.     sprintf(errtext, "Error %d setting resource attributes", rc);
  1987.     showerr(errtext);
  1988.     return(4);
  1989.     }
  1990. else {
  1991.     return(0);
  1992.     }
  1993. }
  1994.  
  1995. int addfont(void)
  1996. {
  1997. Size fntsize, imagesize;
  1998. unsigned short resattr;
  1999. OSErr rc;
  2000. unsigned char errtext[256];
  2001. unsigned char *fontptr, *owptr;
  2002. unsigned short *locptr;
  2003. short i, xpos, copyoffset;
  2004. short vpixsize, hpixsize;
  2005. char foundmissing, foundchar, fixedfont;
  2006. unsigned char firstchar, lastchar, missingchar;
  2007. unsigned short bitwidth, rowwords;
  2008. FontRec *fr;
  2009. GrafPtr gp;
  2010. Rect pRect, srcrect, destrect;
  2011. static unsigned long *Ticks = 0x16a;
  2012. unsigned long t;
  2013.  
  2014.  
  2015. /* get first char, last char., a missing char., fixed or proportional, */
  2016. /* maximum width, and sum of all image widths */
  2017. foundmissing = foundchar = 0;
  2018. fixedfont = 1;
  2019. bitwidth = 0;
  2020. for (i=0; i < 256; i++) {
  2021.     if (scandata[i].missing) {
  2022.         if (foundmissing) {
  2023.             continue;
  2024.             }
  2025.         else {
  2026.             foundmissing = 1;
  2027.             missingchar = i;
  2028.             }
  2029.         }
  2030.     if (scandata[i].pen_right != scandata[256].pen_right) {
  2031.         fixedfont = 0;    /* reset if a different width */
  2032.         }
  2033.     if (!scandata[i].blank) {
  2034.         bitwidth += scandata[i].image_right - scandata[i].image_left;
  2035.         }
  2036.     if (scandata[i].missing) continue;
  2037.     if (!foundchar) {
  2038.         foundchar = 1;
  2039.         firstchar = i;
  2040.         }
  2041.     lastchar = i;
  2042.     }
  2043.  
  2044. /* get handle to data to write out */
  2045. fntsize = (bitwidth + 15) >> 4;                            /* row words */
  2046. rowwords = fntsize;                                        /* save row words */
  2047. fntsize *= scandata[256].image_top - scandata[256].image_bottom;    /* times row count */
  2048. imagesize = fntsize;                                    /* save size in words */
  2049. fntsize <<= 1;                                            /* convert to bytes */
  2050. fntsize += sizeof(FontRec);                                /* font record */
  2051. fntsize += (lastchar - firstchar + 3) << 2;                /* loc. and ow tables */
  2052. fonthandle = NewHandle(fntsize);
  2053. if (fonthandle == 0) {
  2054.     sprintf(errtext, "Out of memory allocating NFNT resource");
  2055.     showerr(errtext);
  2056.     return(1);
  2057.     }
  2058. HLock(fonthandle);
  2059.                     /* initialize all fields to zero */
  2060. memset(*fonthandle, 0, fntsize);
  2061.     
  2062. fontptr = *fonthandle;
  2063. fr = (FontRec *)fontptr;
  2064. if (fixedfont) fr->fontType = 0xb000;
  2065. else fr->fontType = 0x9000;
  2066. fr->firstChar = firstchar;
  2067. fr->lastChar = lastchar;
  2068. fr->widMax = scandata[256].pen_right;
  2069. fr->kernMax = scandata[256].image_left;
  2070. if (fr->kernMax > 0) fr->kernMax = 0;
  2071. fr->nDescent = scandata[256].image_bottom;
  2072. fr->fRectWidth = scandata[256].image_right - scandata[256].image_left;
  2073. fr->fRectHeight = scandata[256].image_top - scandata[256].image_bottom;
  2074. fr->owTLoc = 4 + imagesize + (lastchar - firstchar + 3) + 1;
  2075. fr->ascent = scandata[256].image_top;
  2076. fr->descent = -(scandata[256].image_bottom);
  2077. fr->leading = dlgoutput.leading;
  2078. fr->leading *= dlgoutput.numer.v;
  2079. fr->leading += dlgoutput.denom.v >> 1;
  2080. fr->leading /= dlgoutput.denom.v;
  2081. fr->rowWords = rowwords;
  2082.  
  2083. /* done with font record part of resource; now draw the characters into the
  2084.    bitImage table.  The pen is positioned so that the non-blank characters
  2085.    and the missing character are drawn in order adjacent to each other */
  2086.  
  2087. /* create window to show what we are doing */
  2088. if (myWindow != 0) {
  2089.     CloseWindow(myWindow);
  2090.     myWindow = 0;
  2091.     }
  2092. vpixsize = fr->fRectHeight;
  2093. if (vpixsize > (screenRect.bottom - screenRect.top - 16))
  2094.     vpixsize = screenRect.bottom - screenRect.top - 16;
  2095. hpixsize = screenRect.right - screenRect.left - 16;
  2096. if (hpixsize > bitwidth) hpixsize = bitwidth;
  2097. if (bigscreen) {
  2098.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/3+9;
  2099.     }
  2100. else {
  2101.     pRect.top = (screenRect.bottom-screenRect.top-vpixsize)/2+9;
  2102.     }
  2103. pRect.left = (screenRect.right-screenRect.left-hpixsize)/2-1;
  2104. pRect.bottom = pRect.top+vpixsize;
  2105. pRect.right = pRect.left+hpixsize;
  2106.  
  2107. GetPort(&gp);
  2108.  
  2109. myWindow = NewWindow((Ptr)&wRecord, &pRect, "\pPass Two: Character Imaging",
  2110.                      true, noGrowDocProc, (WindowPtr)-1L, false, 0L);
  2111. fontwindow = 1;
  2112.                     
  2113. pRect.bottom = pRect.bottom - pRect.top;    /* convert to local coordinates */
  2114. pRect.right = pRect.right - pRect.left;
  2115. pRect.top = pRect.left = 0;
  2116.  
  2117.  
  2118. /* define bitmap for characters */
  2119. WriteMap.bounds.top = 0;
  2120. WriteMap.bounds.bottom = fr->fRectHeight;
  2121. WriteMap.bounds.left = 0;
  2122. WriteMap.bounds.right = bitwidth;
  2123. WriteMap.rowBytes = fr->rowWords << 1;
  2124. fontptr += sizeof(FontRec);
  2125. WriteMap.baseAddr = fontptr;
  2126.  
  2127. /* set-up corresponding GrafPort */
  2128. WritePtr = &WritePort;            /* set-up WritePort */
  2129. OpenPort(WritePtr);
  2130. WritePort.portRect = WriteMap.bounds;
  2131. ClipRect(&WritePort.portRect);
  2132. CopyRgn(WritePort.clipRgn, WritePort.visRgn);
  2133. SetPortBits(&WriteMap);
  2134. EraseRgn(WritePort.visRgn);
  2135. TextFont(dlginput.family);
  2136. TextFace(dlginput.face);
  2137. TextSize(dlginput.size);
  2138.  
  2139. srcrect.top = WriteMap.bounds.top;
  2140. srcrect.bottom = WriteMap.bounds.bottom;
  2141. destrect.top = pRect.top;
  2142. destrect.bottom = pRect.bottom;
  2143. while ((srcrect.bottom - srcrect.top) > (destrect.bottom - destrect.top)) {
  2144.     srcrect.top++;
  2145.     }
  2146.  
  2147. SetPort(myWindow);
  2148. xpos = 0;
  2149. copyoffset = 0;
  2150. t = *Ticks;
  2151. MoveTo(pRect.left, pRect.bottom - fr->descent);
  2152. LineTo(pRect.right, pRect.bottom - fr->descent);
  2153. for (i = 0; i < 257; i++) {
  2154.     if (i != 256) {
  2155.         if (scandata[i].missing || scandata[i].blank) continue;
  2156.         }
  2157.     SetPort(WritePtr);
  2158.     if (i == 256) {
  2159.         MoveTo(xpos-scandata[missingchar].image_left, fr->ascent);
  2160.         }
  2161.     else {
  2162.         MoveTo(xpos-scandata[i].image_left, fr->ascent);
  2163.         }
  2164.     UseResFile(resref);
  2165.     if (i == 256) myDrawChar(missingchar);
  2166.     else myDrawChar(i);
  2167.     UseResFile(myref);
  2168.     SetPort(myWindow);
  2169.     srcrect.left = xpos;
  2170.     if (i == 256) {
  2171.         xpos += scandata[missingchar].image_right
  2172.                 - scandata[missingchar].image_left;
  2173.         }
  2174.     else {
  2175.         xpos += scandata[i].image_right - scandata[i].image_left;
  2176.         }
  2177.     srcrect.right = xpos;
  2178.     destrect.left = srcrect.left - copyoffset;
  2179.     destrect.right = destrect.left + srcrect.right - srcrect.left;
  2180.     if (destrect.right > pRect.right) {
  2181.         copyoffset = srcrect.left;
  2182.         destrect.left = srcrect.left - copyoffset;
  2183.         destrect.right = destrect.left + srcrect.right - srcrect.left;
  2184.         EraseRect(&pRect);
  2185.         MoveTo(pRect.left, pRect.bottom - fr->descent);
  2186.         LineTo(pRect.right, pRect.bottom - fr->descent);
  2187.         }
  2188.     while ((*Ticks) < t);
  2189.     CopyBits(&WritePort.portBits, &(myWindow->portBits),
  2190.              &srcrect, &destrect, srcOr, 0L);
  2191.     t = (*Ticks) + DELAYTICKS;
  2192.     }
  2193. while ((*Ticks) < t);
  2194. SetPort(gp);
  2195. ClosePort(WritePtr);
  2196. CloseWindow(myWindow);
  2197. myWindow = 0;
  2198. fontwindow = 0;
  2199.  
  2200. /* loop to define the location table */
  2201. fontptr += imagesize << 1;
  2202. locptr = (unsigned short *)fontptr;
  2203.  
  2204. xpos = 0;
  2205. for (i = firstchar; i <= lastchar; i++) {
  2206.     *locptr = xpos;
  2207.     locptr++;
  2208.     if (scandata[i].missing || scandata[i].blank) continue;
  2209.     xpos += scandata[i].image_right - scandata[i].image_left;
  2210.     }
  2211. *locptr = xpos;
  2212. locptr++;
  2213. xpos += scandata[missingchar].image_right - scandata[missingchar].image_left;
  2214. *locptr = xpos;
  2215.  
  2216. /* loop to define the offset/width table */
  2217. fontptr += (lastchar - firstchar + 3) << 1;
  2218. owptr = fontptr;
  2219. for (i = firstchar; i <= lastchar; i++) {
  2220.     if (scandata[i].missing) {
  2221.         *owptr = 0xff;
  2222.         owptr++;
  2223.         *owptr = 0xff;
  2224.         owptr++;
  2225.         }
  2226.     else {
  2227.         *owptr = scandata[i].image_left - fr->kernMax;
  2228.         owptr++;
  2229.         *owptr = scandata[i].pen_right;
  2230.         owptr++;
  2231.         }
  2232.     }
  2233. *owptr = scandata[missingchar].image_left - fr->kernMax;
  2234. owptr++;
  2235. *owptr = scandata[i=missingchar].pen_right;
  2236. owptr++;
  2237. *owptr = 0xff;
  2238. owptr++;
  2239. *owptr = 0xff;
  2240. owptr++;
  2241.  
  2242. UseResFile(rfile);
  2243. AddResource(fonthandle, 'NFNT', NFNTID, "\P");
  2244. rc = ResError();
  2245. UseResFile(myref);
  2246. if (rc) {
  2247.     sprintf(errtext, "Error %d adding resource to file", rc);
  2248.     showerr(errtext);
  2249.     return(2);
  2250.     }
  2251.  
  2252. resattr = GetResAttrs(fonthandle);
  2253. if (rc = ResError()) {
  2254.     sprintf(errtext, "Error %d getting resource attributes", rc);
  2255.     showerr(errtext);
  2256.     return(3);
  2257.     }
  2258.  
  2259. resattr |= resPurgeable;
  2260.  
  2261. SetResAttrs(fonthandle, resattr);
  2262. if (rc = ResError()) {
  2263.     sprintf(errtext, "Error %d setting resource attributes", rc);
  2264.     showerr(errtext);
  2265.     return(4);
  2266.     }
  2267. else {
  2268.     return(0);
  2269.     }
  2270. }
  2271.  
  2272. void ctrwindow(GrafPtr wp)
  2273. {
  2274. short scrhsize, scrvsize;
  2275. short whsize, wvsize;
  2276.  
  2277. scrhsize = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
  2278. scrvsize = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
  2279. whsize = wp->portRect.right-wp->portRect.left;
  2280. wvsize = wp->portRect.bottom - wp->portRect.top;
  2281. MoveWindow(wp, (scrhsize-whsize)/2, (scrvsize-wvsize)/3, 0);
  2282. }
  2283.  
  2284. void framedflt(DialogPtr dlgptr)
  2285. {
  2286. short gtype;
  2287. Handle gitem;
  2288. Rect gbox;
  2289. GrafPtr gp;
  2290.  
  2291. GetDItem(dlgptr, 1, >ype, &gitem, &gbox);
  2292. GetPort(&gp);
  2293. SetPort(dlgptr);
  2294. PenSize(3,3);
  2295. InsetRect(&gbox, -4, -4);
  2296. FrameRoundRect(&gbox, 16, 16);
  2297. SetPort(gp);
  2298. }
  2299.